Перейти к основному содержимому

Юнит-тестирование AngularJS с Karma и Jasmine

· 3 мин. чтения

Я когда-то писал про тестирование javascriptа с помощью jstestdriver , поскольку тот был первым интегрированным в PHPStorm, но инструменты развиваются и теперь для ангуляра есть простор для проверки качества кода.

Karma это консольный инструмент для запуска тестов согласно конфиг файлу. Тесты гоняются в разных браузерах, умеет следить за изменениями исходников и генерировать покрытие кода. Есть ещё protractor - близкий по смыслу но для системных тестов.

Jasmine это уже библиотека для тестирования, аналог Mocha.

Для установки всего набора:

npm install karma -g
npm install phantomjs -g
npm install karma-jasmine karma-chrome-launcher karma-phantomjs-launcher istanbul --save
bower install angular-mocks

 

Теперь надо добавить karma.conf.js где надо указать пути к файлам которые будут подключаться и пути к тестам. Для этого проще всего запустить karma init - он создаст шаблон

После того как тесты написаны - надо запустить karma start. При прогоне тестов с установленным istanbul, в папку coverage будет генерироваться html с детальным покрытием. Для ангуляра нужна angular-mocks

Jasmine

Jasmine пожалуй самый популярный сейчас фреймворк для js-тестов. Структура файлов довольно простая и в нём ключевые слова:

  • describe() - оборачивает тесты в test-suite

  • beforeEach() и afterEach() - соответсвенно запускаются для каждого теста

  • it('название теста', function()) - сам тест

  • iit() и xit() - выделяют тест что-бы прогнать только его или игнорировать его соответственно

Promise-объекты

Сложность при работе с js в том что код асинхронный, а значит тесты не могут ждать неизвестно сколько времени, покуда исполнится скрипт. Поэтому паттерн задержанных обьектов-обещаний (deferred в jquery и promise в angular соответсвенно), полезны в тестировании тем что их можно преждевременно заменять в моках и сразу же resolve'ить на нужные результаты.

Наиболее частый случай таких замен - ajax запросы. В angular имеется $http сервис и для него уже существует $httpBackend мок, которым легко эмулировать весь обмен данными с backend. Есть ещё $timeout и $exceptionHandlerProvider для особенных случаев

Пример теста

Набор юнит-тестов сервиса у меня в общем выглядит так

describe('In memory cache service', function () {
var objectToTest;
var $httpBackend;

beforeEach(function () {
module('app');

inject(function ($injector) {
objectToTest = $injector.get('MemoryService');

$httpBackend = $injector.get('$httpBackend');
$rootScope = $injector.get('$rootScope');
});
});

afterEach(function () {
$httpBackend.flush();
$httpBackend.verifyNoOutstandingExpectation();
$httpBackend.verifyNoOutstandingRequest();
});

it('should have a MemoryService', function () {
expect(app.MemoryService).toBeDefined();
});

it('setter and getter check', function () {
var v = {a: 1};
objectToTest.setCache(v);
expect(objectToTest.getCache()).toEqual(v);
objectToTest.emptyCache();
expect(objectToTest.getCache()).toEqual({});
});

it('should recieve data', function(){
var exampleData = {
1:{'username':'JamesBond'}
};

$httpBackend.expectGET('api/users').respond(exampleData);
objectToTest.loadOverNetwork().then(function(){
expect(objectToTest.getCache()).toEqual(exampleData);
});
});


it('should not clear cache on error', function(){
var exampleData = {
1:{'username':'JamesBond'}
};
objectToTest.setCache(exampleData)
$httpBackend.expectGET('api/users').respond(404, false);

objectToTest.loadOverNetwork().then(function(){}, function(){
expect(objectToTest.getCache()).toEqual(exampleData);
});
});
});

Я ещё не успел проапгрейдится до PHPStorm 7, где есть тесная интеграция с кармой, поэтому у меня тесты выводятся в консольке..

Ссылки

По теме, с увеличивающейся сложностью: